/*
 * Copyright 2014-2024 TNG Technology Consulting GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.tngtech.archunit.library.cycle_detection;

import java.util.Collection;

import com.tngtech.archunit.PublicAPI;

import static com.tngtech.archunit.PublicAPI.State.EXPERIMENTAL;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;

/**
 * @see #detectCycles(Collection, Collection)
 */
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public final class CycleDetector {
    private CycleDetector() {
    }

    /**
     * Detects cycles in directed graphs consisting of nodes of type {@code NODE} which are connected
     * by directed edges of type {@code EDGE}.<br>
     * All reported cycles are "simple" cycles, i.e. they pass each node at most once.
     * The algorithm reports all such simple cycles, even if nodes / edges are already part of another cycle.
     * Consider the following case:
     * <p>
     * <img src="">
     * </p>
     * Then both cycles, red and blue, would be reported.<br><br>
     * For performance reasons the {@link CycleDetector} has a maximum number of cycles to detect.
     * Once this limit is reached the algorithm will terminate and all cycles so far will be reported.
     * For further information please refer to {@link Cycles#maxNumberOfCyclesReached()}.<br><br>
     * Note that the given edges must only reference the given nodes as their {@link Edge#getOrigin() origin} and
     * {@link Edge#getTarget() target} or an exception will be thrown.<br>
     * Also, the passed {@code NODE} types must implement an appropriate and reasonably performant {@link Object#equals(Object)}
     * and {@link Object#hashCode()}.
     *
     * @param nodes The nodes of the graph to create
     * @param edges The edges connecting the nodes of the graph
     * @return All cycles within the graph created from the passed nodes and edges.
     */
    @PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
    public static <NODE, EDGE extends Edge<NODE>> Cycles<EDGE> detectCycles(Collection<NODE> nodes, Collection<EDGE> edges) {
        Graph<NODE, EDGE> graph = new Graph<>();
        graph.addNodes(nodes);
        graph.addEdges(edges);
        return graph.findCycles();
    }
}
